package cn.lili;

import com.alibaba.fastjson.JSON;
import com.jfinal.kit.Ret;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

public class TestWechat {
    static String merchantId = "1630374082";
    static String merchantSerialNumber = "7E0B405BADCABAA9649C49A9E9DA9343015CDEC2";
    static String apiV3Key = "rbYj104SbYObSwiXz9XFpgTQQlrXpwCW";

    static {

        PrivateKey pk = null;
        try {
//            pk = PemUtil.loadPrivateKey(new FileInputStream(new File("D:\\source\\lilishop\\cert\\wechat\\1630374082_20220819_cert\\apiclient_key.pem")));
            pk = PemUtil.loadPrivateKey(new FileInputStream(new File("D:\\source\\lilishop\\cert\\wechat\\apiclient_key.pem")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();

        // 向证书管理器增加需要自动更新平台证书的商户信息
        try {
            certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId,
                    new PrivateKeySigner(merchantSerialNumber, pk)), apiV3Key.getBytes(StandardCharsets.UTF_8));
        } catch (IOException | GeneralSecurityException | HttpCodeException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws InterruptedException, IOException, NotFoundException {
        Thread.sleep(1000);
//        List<Ret> subOrders = new ArrayList<>();
//        subOrders.add(
//                Ret.create().set("mchid", "1630374082").set("attach", "1562330943618924546").set("amount", Ret.create("total_amount", 50).set("currency", "CNY")).set("out_trade_no", System.currentTimeMillis() + "" + RandomUtils.nextInt(10000, 100000)).set("sub_mchid", "1630775004").set("description", "冠佩商城-测试1")
//        );
////        subOrders.add(
////                Ret.create().set("mchid", "1630374082").set("attach", "1562330943618924546").set("amount", Ret.create("total_amount", 50).set("currency", "CNY")).set("out_trade_no", System.currentTimeMillis() + "" + RandomUtils.nextInt(10000, 100000)).set("sub_mchid", "1630756256").set("description", "冠佩商城-测试2")
////        );
//        Ret param = Ret.create();
//        param.set("combine_appid", "wx558d2fefc15e7d7c");
//        param.set("combine_mchid", "1630374082");
//        param.set("combine_out_trade_no", System.currentTimeMillis() + "");
//        param.set("notify_url", "http://www.hnguanpei.cn/buyer/payment/cashier/notify/WECHAT");
////        param.set("scene_info", Ret.create("device_id", "WEB").set("payer_client_ip", "127.0.0.1").set("h5_info", Ret.create().set("type", "Wap")));
//        param.set("sub_orders", subOrders);
//        System.out.println(JSON.toJSONString(param, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue
//                , SerializerFeature.WriteDateUseDateFormat));
//        sPayNative(true, param);
////        sPayNative(true, param);
////        getApplyment("2000002318019284", null);
////        verfy1();
////        verfy2();
        //returnAdvance("50302002892022090524568387103", "1630775004");

        Ret refundParam = Ret.create().set("sp_appid", "wx558d2fefc15e7d7c")
                .set("sub_mchid", "1631286511")
                .set("transaction_id", "4332400954202209056365613359")
                .set("out_refund_no", "ff808081830e39fa01830e3a14fb0007_1")
                .set("reason", "协商退款")
//                .set("refund_account", StringUtils.defaultIfEmpty(param.getStr("refundAccount"), "REFUND_SOURCE_SUB_MERCHANT"))
                .set("amount", Ret.create().set("currency", "CNY").set("refund", 6).set("total", 20));
        System.out.println(JSON.toJSONString(refundParam));
        refundApply(refundParam);
    }

    @SneakyThrows
    public static void refundApply(Ret param) {
        CloseableHttpClient httpClient = getHttpClient();
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/refunds/apply");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        IOUtils.write(param.toJson(), bos, "utf-8");

        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        }
    }

    public static void verfy1() throws NotFoundException {
        String timestamp = "1661693239";
        String nonce = "0VXbkCitSlDYB5TnvrOGPMG3J4HRvX7B";
        String serialNo = "5738CDEF0FD4A0FF368C8D6780222AD53A1B327B";
        String signature = "eLtN6cWFUqbFod7LLAVEfhv9lF32WskPtzyrcHJmk9g51gxqXHqFDoRBAJ80Z3PjBntpDXf4w0zzoFwy64pcFZ0piFWPMjIuTISxXJ6bTZj5lStbASUXcK+wncgmJBzOduMQix0QR+urjh8+UiN5DSMJwXY1Zocq2hsEGFzPR9JHj9/lR3TnSo1nZNNnqPHrsQF7zwDhV8metuUjD48Cv9CVkakQk9jaooxWZwkavEkwYXTVXjFMJSQnMyEdwJmZakHtLxaHypWfHT0XEL0VN/7oiTpvL04aUGQc3Ie4TSNe1OVDgZnEgucJt00R8wAXQdaBTHVRg0vYnOI9mTK9Ng==";
        String result = "{\"resource_type\":\"encrypt-resource\",\"summary\":\"支付成功\",\"id\":\"22c580aa-4fb4-5318-9122-772b93d3a827\",\"event_type\":\"TRANSACTION.SUCCESS\",\"create_time\":\"2022-08-28T21:27:18+08:00\",\"resource\":{\"original_type\":\"transaction\",\"algorithm\":\"AEAD_AES_256_GCM\",\"ciphertext\":\"PbKgdfMtK9fAuwh1S8invHm3oqpkm16JnQsJonKtGqspeqZ2Uq0318iVRIsJb4vtNkXJp18jnEZSl/ub+z6YY8fcWdzZjpbDOloDpEGSDbXpqjFDo8RS5wJ9TRSkpxKmt0PZHNhuAnyJ2jqm3B1iK/hdv+teEwMqM+3dof/rTjweHTErfAT0xsjRR8/uFoo7KsgRhRZ5c/mrme7KT4y25hHShK0yd8mLqCETv9/yJvI+jNBxY8mZF01uoUX0gwNfCfpQfvH3Gnlwfh1irDKSJl1q/Qu/fFJUEU6OJzh8DNbBw8WRA/ZAEq68KLceg7QD3pe4DCeHmPU7RxWrPxSFk1sgqVEnoizQH6cwvJ4dl2wFzzVNu2t6hF1lKV3JW6g+7ZSS7OV7XoWQlBXEABFRY7Qv9RDf1ePh4o9uG5+Zx084Tey8Smhbdvs7Vg3v1mrhlR0vszTUsT2PcE1kz47ixGnbLz7T6UEt3q8ad7aHVutsIaSrArXxW2+m6C4lteDFuHkJu5wIhakRUrUcEbktW0OuWg7ILb27d//egB/+SsXJm/d0ZtrOHdRjUEwZj0rqq0ya1Ylkv1w+pU1KVaaARubl4SWGTEZ5Vl5CULuND1uYKqWsMh+GQ9t9bv4Mub2ve0KyZeBERcQ1Z67cNxh1kIOU\",\"associated_data\":\"transaction\",\"nonce\":\"yb59hZ0zgYox\"}}";
        Verifier verifier = CertificatesManager.getInstance().getVerifier(merchantId);
        String signContent = timestamp + "\n" + nonce + "\n" + result + "\n";
        boolean verify = verifier.verify(serialNo, signContent.getBytes(StandardCharsets.UTF_8), signature);
        System.out.println("验证1验证结果：" + verify);
    }

    public static void verfy2() throws NotFoundException {
        String timestamp = "1661688005";
        String nonce = "R8qUhali41wtJfNYQgdeh6HkIX52IIc7";
        String serialNo = "5738CDEF0FD4A0FF368C8D6780222AD53A1B327B";
        String signature = "GnQwoK0950eb4uJyxiNavmbMpzge8A3maaRc5F/ZrYsbrBrP5GWID/Xp8hQ7iU18iUI2olKMswYhvyeVnAicnHBLjanZu546zMLXi+CUJ/MRkhi5YE/SH53RjrAPgakyvXYSs27q90zfXMVm0v4jldhpyjJM8w6AHcd/dnk0rf1G1ksQysN29pnzDz4W0Xs0t7yyToA4KmAfVY3bo4wAX6tm4oMAu6XTVphd2QFm/CVOg2dr8e0XnYSQNc5C3eLVKMPQJlfD4XuZcR6Ast4PKEmtbXdl++Q4+I+qRdYWS8HZ4Xl8CFqRsju25KEW52jro1LKcpyelwYEkg/Ner6UMg==";
        String result = "{\"id\":\"a5fb8518-3842-52f4-b27b-70846273b7b5\",\"create_time\":\"2022-08-28T20:00:04+08:00\",\"resource_type\":\"encrypt-resource\",\"event_type\":\"TRANSACTION.SUCCESS\",\"summary\":\"支付成功\",\"resource\":{\"original_type\":\"transaction\",\"algorithm\":\"AEAD_AES_256_GCM\",\"ciphertext\":\"mHJp7kS1vEmb4a6qI9/R+4k7h1L7UB4Anxd446bxjgXUj59mNdMn0DS8s1BlRTszXfi2nJ8S2J8htLioCIVfJcUnF/kq3lmmV+/WgxKzcLJioI2OLdyaRCWRi7IzxsVxcgFecnpnYDE2OnFBtbDoOn5MeO+HJHaJH7pLz2ISzbCJ857hKWcQIZMkvWj9UuM4Q1GFv9+Wdz2FSIIac0pG2hNFzpUPvrM3vFRXaa/ZlVeffAcI8LlCKluJayPeQ7WsWSfAcn/6ZvFdX5m9b2mdR4EkBcr312aEJgXEf9stL3CLIlvZf6OSn20CWnKi0CDruj99b/vIyJJI7PEQrgw8tfVzpcbe7JvkeUqTtk9dcxbdO0kvY2D60LW2yEdN0dT5BCmXB6uirm8idTGHgMebh97LmhEqT/12xbK8ALnNge87th+eSCZtHa+oat05Weaozc9x9XhXja1Rj2SlPEhPwDUEsFyHnDqoutYP1RELrdHaWdpAYgl5YzfRQsPvWMjUE1OsTcnlAx+Pr4fzZiyA/L1aq6qNeyHS4AaBTVw18NCBLeYrJMunT44iimHf7/9s6CRBXymgmJhlt3jeXXb9L5WByXFZxHZZJyLWhnm41MDibc2WmLisuIuOJkjovDZryj0O99TAtkAwV4bk93/4aOdUyiN9bJoacSj6gKKzhc+5tCAqci7Y/tz/NC4db0uEGE4yXu/4W2KCZihUkIVvOFdUbzW/YOVsDe3PoGb8u59c3l8MjUKfk0eBVr+FvrJ0HI1mh73VtbZA50aoBlk=\",\"associated_data\":\"transaction\",\"nonce\":\"Xtu80qoXEPhn\"}}";
        Verifier verifier = CertificatesManager.getInstance().getVerifier(merchantId);
        String signContent = timestamp + "\n" + nonce + "\n" + result + "\n";
        boolean verify = verifier.verify(serialNo, signContent.getBytes(StandardCharsets.UTF_8), signature);
        System.out.println("验证1验证结果：" + verify);
    }

    public static void getApplyment(String applymentId, String outRequestNo) throws IOException, NotFoundException {
        CloseableHttpClient httpClient = getHttpClient();

        String url = null;
        if (StringUtils.isNotEmpty(applymentId)) {
            url = "https://api.mch.weixin.qq.com/v3/ecommerce/applyments/" + applymentId;
        } else if (StringUtils.isNotEmpty(outRequestNo)) {
            url = "https://api.mch.weixin.qq.com/v3/ecommerce/applyments/out-request-no/" + outRequestNo;
        }
        HttpGet httpGet = new HttpGet(url);
        httpGet.addHeader("Accept", "*/*");

        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        }
    }

    @SneakyThrows
    public static void sPayNative(boolean isCombine, Ret param) {
        CloseableHttpClient httpClient = getHttpClient();
        String url;
        if (isCombine) {
            url = "https://api.mch.weixin.qq.com/v3/combine-transactions/native";
        } else {
            url = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/native";
        }
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        IOUtils.write(param.toJson(), bos, "utf-8");

        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));

        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        }
    }


    static CloseableHttpClient getHttpClient() throws NotFoundException {
        PrivateKey pk = null;
        try {
            pk = PemUtil.loadPrivateKey(new FileInputStream(new File("D:\\source\\lilishop\\cert\\wechat\\apiclient_key.pem")));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息
        // 从证书管理器中获取verifier
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(merchantId, merchantSerialNumber, pk)
                .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(merchantId)));
        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新

        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient
        return builder.build();
    }

    @SneakyThrows
    public static void sPayH5(boolean isCombine, Ret param) {
        CloseableHttpClient httpClient = getHttpClient();
        String url;
        if (isCombine) {
            url = "https://api.mch.weixin.qq.com/v3/combine-transactions/h5";
        } else {
            url = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/h5";
        }
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        IOUtils.write(param.toJson(), bos, "utf-8");

        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));

        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        }
    }

    @SneakyThrows
    public static void returnAdvance(String refundId, String subMchId) {
        CloseableHttpClient httpClient = getHttpClient();
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/refunds/" + refundId + "/return-advance");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        IOUtils.write(Ret.create("sub_mchid", subMchId).toJson(), bos, "utf-8");

        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        }
    }
}


